package org.example.r;

/**
 * @author 季舟
 * @Date 2025-01-16 13:43
 */

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class RunRScriptExample {
    public static void main(String[] args) throws Exception {
        runRScriptGetPlot();
    }

    /**
     * 使用参数运行R脚本
     * 此方法通过Java调用R脚本，并传递参数进行计算
     * 具体来说，它将一个整数数组传递给R脚本，并计算这些数字的总和
     *
     * @throws Exception 如果在执行过程中无法连接到Rserve或脚本执行失败，则抛出异常
     */
    public static void runRScriptWithParam() throws Exception {

        // 获取resources文件夹中的script.R文件路径
        ClassLoader classLoader = RunRScriptExample.class.getClassLoader();
        Path scriptPath = Paths.get(classLoader.getResource("r_script/sum_script.r").toURI());
        File scriptFile = scriptPath.toFile();
        // 检查脚本文件是否存在，如果不存在则抛出异常
        if (!scriptFile.exists()) {
            throw new IOException("R script file not found: " + scriptFile.getAbsolutePath());
        }

        // 定义一个整数数组，用于后续传递给R脚本
        int[] datas = {314, 451, 56, 24, 2631};

        // 创建RConnection对象以连接Rserve
        RConnection c = new RConnection();
        // 将脚本文件路径和数据数组传递给R
        c.assign("fileName", scriptFile.getAbsolutePath());
        c.assign("datas", datas);

        // 执行R脚本
        c.eval("source(fileName)");

        // 调用R脚本中的sumFunction函数，并获取结果
        REXP eval = c.eval("sumFunction(datas)");
        // 打印计算结果
        System.out.println(eval.asInteger());

        // 关闭连接
        c.close();
    }

    /**
     * 运行R脚本
     * 该方法连接到本地运行的Rserve，执行预定义的R脚本，并处理结果
     * 需要确保Rserve正在运行，并且脚本文件位于resources文件夹中
     *
     * @throws Exception 如果在执行R脚本或处理过程中遇到错误，抛出此异常
     */
    public static void runRScript() throws Exception {
        // 创建RConnection实例，连接到本地运行的Rserve
        RConnection c = new RConnection();

        // 获取resources文件夹中的script.R文件路径
        ClassLoader classLoader = RunRScriptExample.class.getClassLoader();
        Path scriptPath = Paths.get(classLoader.getResource("r_script/script.R").toURI());
        File scriptFile = scriptPath.toFile();

        // 检查脚本文件是否存在，如果不存在则抛出异常
        if (!scriptFile.exists()) {
            throw new IOException("R script file not found: " + scriptFile.getAbsolutePath());
        }

        // 读取脚本内容
        String scriptContent = new String(Files.readAllBytes(scriptFile.toPath()));
        // 统一换行符
        scriptContent = scriptContent.replace("\r\n", "\n").replace("\r", "\n");

        // 打印脚本内容（用于调试）
        System.out.println("R Script Content:\n" + scriptContent);

        // 执行R脚本
        c.eval(scriptContent);

        // 获取结果，将R中的x和y序列转换为Java的double数组
        double[] x = c.eval("x").asDoubles();
        double[] y = c.eval("y").asDoubles();

        // 打印结果，遍历数组x和y，输出每个元素的值
        for (int i = 0; i < x.length; i++) {
            System.out.println("x[" + i + "] = " + x[i] + ", y[" + i + "] = " + y[i]);
        }

        // 关闭连接
        c.close();
    }


    /**
     * 运行R脚本并生成散点图
     * 该方法通过Rserve连接执行R脚本，生成并保存散点图
     * @throws Exception 当执行过程中遇到错误时抛出异常
     */
    public static void runRScriptGetPlot() throws Exception {
        // 获取resources文件夹中的script.R文件路径
        ClassLoader classLoader = RunRScriptExample.class.getClassLoader();
        Path scriptPath = Paths.get(classLoader.getResource("r_script/age_weight_plot.r").toURI());
        File scriptFile = scriptPath.toFile();
        // 检查脚本文件是否存在，如果不存在则抛出异常
        if (!scriptFile.exists()) {
            throw new IOException("R script file not found: " + scriptFile.getAbsolutePath());
        }

        // 定义保存图片的路径
        String plotFilePath = "D://age_weight_plot.png";

        // 定义age和weight数组
        int[] age = {100, 3, 5, 2, 11, 9, 3, 9, 12, 3};
        double[] weight = {4.4, 5.3, 7.2, 5.2, 8.5, 7.3, 6.0, 10.4, 10.2, 6.1};

        // 创建RConnection对象以连接Rserve
        RConnection c = new RConnection();
        // 将脚本文件路径、图片保存路径、age和weight数组传递给R
        c.assign("fileName", scriptFile.getAbsolutePath());
        c.assign("plotFilePath", plotFilePath);
        c.assign("age", age);
        c.assign("weight", weight);

        // 执行R脚本
        c.eval("source(fileName)");
        // 关闭连接
        c.close();

        // 打印图片保存路径
        System.out.println("Plot saved to: " + plotFilePath);
    }

}


